package main

import (
	"context"
	"fmt"
	"go.etcd.io/etcd/clientv3"
	"time"
)

func main() {
	var (
		config        clientv3.Config
		client        *clientv3.Client
		err           error
		lease         clientv3.Lease
		leaseResp     *clientv3.LeaseGrantResponse
		leaseId       clientv3.LeaseID
		keepAliveChan <-chan *clientv3.LeaseKeepAliveResponse
		keepAliveResp *clientv3.LeaseKeepAliveResponse
		ctx           context.Context
		cancelFunc    context.CancelFunc
		kv            clientv3.KV
		txn           clientv3.Txn
		txnResponse   *clientv3.TxnResponse
	)

	config = clientv3.Config{
		Endpoints:   []string{"localhost:2379"},
		DialTimeout: 5 * time.Second,
	}

	if client, err = clientv3.New(config); err != nil {
		fmt.Print(err)
		return
	}

	//上锁(创建租约  自动续租 抢占key
	lease = clientv3.NewLease(client)

	ctx, cancelFunc = context.WithCancel(context.TODO())
	defer cancelFunc()
	defer lease.Revoke(context.TODO(), leaseId)

	if leaseResp, err = lease.Grant(ctx, 5); err != nil {
		fmt.Print(err)
		return
	}
	leaseId = leaseResp.ID
	if keepAliveChan, err = lease.KeepAlive(context.TODO(), leaseId); err != nil {
		fmt.Print(err)
		return
	}
	go func() {
		for {
			select {
			case keepAliveResp = <-keepAliveChan:
				fmt.Println("自动续租", keepAliveResp.ID)
			}
		}
	}()

	//业务逻辑
	kv = clientv3.NewKV(client)
	txn = kv.Txn(context.TODO())
	txn.If(clientv3.Compare(clientv3.CreateRevision("/cron/lock/version"), "=", 0)).
		Then(clientv3.OpPut("/cron/lock/version", "", clientv3.WithLease(leaseId))).
		Else(clientv3.OpGet("/cron/lock/version"))

	if txnResponse, err = txn.Commit(); err != nil {
		fmt.Println(err)
		return
	}

	if !txnResponse.Succeeded {
		fmt.Println("抢锁失败")
		return
	}

	fmt.Println("处理业务")
	time.Sleep(5 * time.Second)
	//释放锁(取消自动续租 释放租约)  defer

}
